home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
129_01
/
hack.doc
< prev
next >
Wrap
Text File
|
1985-03-09
|
23KB
|
500 lines
/************************************************************************/
/* hack.doc */
/************************************************************************/
/************************************************************************/
/* History */
/* */
/* 82Dec07 CrT Completed. */
/* 82Nov23 CrT Created. */
/************************************************************************/
/************************************************************************/
/* Audience */
/* */
/* Folks trying to read or modify the Citadel code. */
/************************************************************************/
/************************************************************************/
/* Purpose */
/* */
/* Explain the basic data structures and algorithms. */
/************************************************************************/
/************************************************************************/
/* Overview */
/************************************************************************/
The fundamental structure of the system is very simple. CtdlMsg.sys
is a circular file. New messages are simply written around the buffer
in an endless circle, overwriting old messages in their way. There is
no other way of deleting messages, and text is never shuffled on disk.
Messages are numbered consecutively and start with an FF (hex)
byte. Except for this FF start-of-message byte, all bytes in the message
file have the high bit set to 0. This means that in principle it is
trivial to scan through the message file and locate message N if it
exists, or return error. (Complexities, as usual, crop up when we
try for efficiency...)
Each room is basically just a list of message numbers. Each time
we enter a new message in a room, we slide all the old message-numbers
down a slot, and probably the oldest one falls off the bottom. Reading
a room is just a matter looking up the messages one by one and printing
them out. If the message has been overwritten already, we just ignore it.
Implementing the "new message" function is also trivial in principle:
we just keep track, for each caller in the userlog, of the highest-numbered
message which existed on the >last< call. (Remember, message numbers are
simply assigned sequentially each time a message is created. This
sequence is global to the entire system, not local within a room.) If
we ignore all message-numbers in the room less than this, only new messages
will be printed. Voila! Code up the system described thus far, and
you'll have a good approximation to Version 1. Better stop and reread
everything to here, so you can pick out the fundamental mechanisms among
all of Version 2's bells and whistles.
/************************************************************************/
/* message format on disk (ctdlMsg.sys) */
/************************************************************************/
Message format has changed relative to V1, in the direction of using
more disk space and providing greater flexibility.
A message now consists of a sequence of character strings. Each string
begins with a type byte indicating the meaning of the string and is
ended with a null. All strings are printable ASCII: in particular,
all numbers are in ASCII rather than binary. This is for simplicity,
both in implementing the system and in implementing other code to
work with the system. For instance, a database driven off Citadel archives
can do wildcard matching without worrying about unpacking binary data such
as dates first. To provide later downward compatability,
all software should be written to IGNORE fields not currently defined.
/************************************************************************/
/* The type bytes currently defined are: */
/************************************************************************/
BYTE Mnemonic Comments
0xFF Start-of-message indicator. Followed by local
message ID# as ASCII string, null-terminated as
always. This byte is the >only< byte which has
the high bit set in a Citadel message.buf file.
This field must be present in every message.
A Author Name of originator of message.
D Date Date message was created.
M Message Text of message. Is last field in a message, by
definition. Following data will be ignored.
This field must be present in every message.
N Name Human name for node originated on. Used on
title line of foreign messages. Ex:
ODD-DATA
will produce a title message something like
82Nov23 from Cynbe ru Taren @ODD-DATA
O Origin ID of node message originated on: Country code plus
phone number of system. (Not stored for locally
originated messages.) Ex:
US 206 633 3282
R Room Room of origin. Topic.
S Source ID# Message ID # on system message was created on.
Two 16-bit integers (high and low halves of
full 32-bit ID#) separated by a blank. Ex:
0 13654
T To Addressee. Used only for private messages in Mail>,
in version 2.00 .
EXAMPLE
Let <FF> be a 0xFF byte, and <0> be a null (0x00) byte. Then a message
which prints as
LOGLAN> read new
82Nov04 From James Cooke Brown
Loi uiue i Ti logla
LOGLAN>
might be stored as
<FF>0 3583<0>D82Nov04<0>AJames Cooke Brown<0>RLOGLAN<0>MLoi uiue i Ti logla<0>
|--Local ID--|---Date---|-----Author---------|--Room---|-------Message--------|
The date, room and author fields could be in any order. Not all fields
are printed by default. The local ID# and Room field are suppressed here.
An isolated system will not normally have use for fields beyond those
used in this example.
Lines are marked with C NewLine (ASCII LF) characters, within the message
text proper.
/************************************************************************/
/* Networking */
/************************************************************************/
Citadel nodes network by sharing one or more rooms. Any Citadel node
can choose to keep an image of any public room on any other Citadel node
(subject to willingness to foot the phone bills, of course!). The
procedure in essence simply involves calling the imaged node up periodically
and copying any new messages in the imaged room into the local image.
There is no necessary reciprocity or pre-arrangement, although convenience
and politeness respectively suggest both. The node which gets the
information foots the phone bill for the transaction. This promotes
simple and harmonious relations between the nodes.
Complexities arise primarily from the possibility of densely connected
networks: one does not wish to accumulate multiple copies of a given
message, which can easily happen. Nor does one want to see old messages
percolating indefinitely through the system.
This problem is handled by a simple brute-force mechanism: each node
keeps a list of all messages it has seen recently, recording origin
system, creation date, and original ID#. When downloading, messages
which have already been seen, or which are too old to be remembered,
are skipped. Messages can percolate outward through a large network
with no global routing or control, but do not reproduce wildly or
cycle indefinitely.
The above discussion should make the function of the new
fields reasonably clear:
o Every message needs a local ID#, so the system can determine if
a given caller has seen it before.
o Travelling messages need to carry system of origin, date of
origin, and original ID# with them, to keep reproduction and
cycling under control.
(Uncoincidentally) the format used to transmit messages for networking
purposes is precisely that used on disk, except that lines are marked
with ASCII CR characters in stead of ASCII LF characters. The current
distribution does not include active network support code; these comments
are included in the hope of discouraging people from modifying the disk
format, date field or whatever in ways which will make their local no